package com.ds.lens.data.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.Page;
import com.ds.lens.data.common.asserts.Asserts;
import com.ds.lens.data.common.client.vo.LensApplicationOutVO;
import com.ds.lens.data.common.constant.Constants;
import com.ds.lens.data.common.document.datasource.LensDsSchema;
import com.ds.lens.data.common.document.datasource.LensDsSource;
import com.ds.lens.data.common.document.datasource.LensDsSql;
import com.ds.lens.data.service.dao.LensDatasourceDao;
import com.ds.lens.data.service.dao.entity.LensDatasource;
import com.ds.lens.data.vo.in.PagedConditionInVO;
import com.ds.lens.data.vo.in.User;
import com.ds.lens.data.vo.in.v2.datasource.LensDatasourceInVO;
import com.ds.lens.data.vo.in.v2.datasource.LensDatasourceListInVO;
import com.ds.lens.data.vo.out.PageResult;
import com.ds.lens.data.vo.out.v2.datasource.LensDatasourceOutVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @author WeiShaoying
 * @date 2020/5/12 上午11:17
 */
@Service
public class LensDatasourceService extends BaseService {
    @Autowired
    LensDatasourceDao lensDatasourceDao;

    @Autowired
    LensApplicationService lensApplicationService;

    @Transactional
    public boolean saveDatasource(LensDatasourceInVO datasourceInVO, User user) {
        checkUserApplication(user, datasourceInVO.getApplicationId());
        LensDatasource datasource = new LensDatasource();
        BeanUtils.copyProperties(datasourceInVO, datasource);
        datasource.setId(null);
        datasource.setType(1);
        datasource.setCreator(user.getUsername());
        datasource.setCreatedTime(new Date());
        datasource.setMender(user.getUsername());
        datasource.setModifiedTime(datasource.getCreatedTime());
        objectToString(datasource, datasourceInVO);
        LensApplicationOutVO lensApplicationOutVO = lensApplicationService.findLensApplicationById(datasource.getApplicationId());
        Asserts.assertTrue(lensApplicationOutVO != null, Constants.ErrorCode.DATA_NOT_EXIST);
        datasource.setApplicationKey(lensApplicationOutVO.getAppKey());
        lensDatasourceDao.insertSelective(datasource);
        return true;
    }

    @Transactional
    public boolean updateDatasource(LensDatasourceInVO datasourceInVO, User user) {
        checkUserApplication(user, datasourceInVO.getApplicationId());
        Asserts.assertTrue(datasourceInVO.getId() != null, Constants.ErrorCode.DATA_NOT_EXIST);
        LensDatasource datasource = lensDatasourceDao.selectByPrimaryKey(datasourceInVO.getId());
        Asserts.assertTrue(datasource != null, Constants.ErrorCode.DATA_NOT_EXIST);
        checkUserApplication(user, datasource.getApplicationId());
        BeanUtils.copyProperties(datasourceInVO, datasource);
        datasource.setMender(user.getUsername());
        datasource.setModifiedTime(datasource.getCreatedTime());
        datasource.setType(1);
        objectToString(datasource, datasourceInVO);
        lensDatasourceDao.updateByPrimaryKeySelective(datasource);
        return true;

    }

    public PageResult<LensDatasourceOutVO> listDatasource(PagedConditionInVO<LensDatasourceListInVO> conditionInVO, User user) {
        getPageCondition(conditionInVO);
        if (CollectionUtils.isEmpty(conditionInVO.getCondition().getApplicationIds())) {
            checkUserApplication(user);
            conditionInVO.getCondition().setApplicationIds(user.getApplicationIds());
        } else {
            checkUserApplication(user, conditionInVO.getCondition().getApplicationIds());
        }
        Page<LensDatasource> page = lensDatasourceDao.listDatasource(conditionInVO.getCondition());
        if (CollectionUtils.isEmpty(page.getResult())) {
            return PageResult.of(Collections.emptyList(), 0L, page.getPageNum(), page.getPageSize());
        }
        List<LensDatasourceOutVO> datasourceOutVOS = new ArrayList<>(page.getPageSize());
        page.getResult().forEach(datasource -> {
            LensDatasourceOutVO datasourceOutVO = new LensDatasourceOutVO();
            BeanUtils.copyProperties(datasource, datasourceOutVO);
            datasourceOutVO.setCreatedTime(datasource.getCreatedTime().getTime());
            datasourceOutVO.setModifiedTime(datasource.getModifiedTime().getTime());
        });
        return PageResult.of(datasourceOutVOS, page.getTotal(), page.getPageNum(), page.getPageSize());
    }

    public LensDatasourceOutVO getDatasource(Long id) {
        LensDatasource datasource = lensDatasourceDao.selectByPrimaryKey(id);
        if (datasource == null) {
            return null;
        }
        LensDatasourceOutVO datasourceOutVO = new LensDatasourceOutVO();
        BeanUtils.copyProperties(datasource, datasourceOutVO);
        datasourceOutVO.setSource(JSON.parseObject(datasource.getSource(), LensDsSource.class));
        datasourceOutVO.setDsSchema(JSON.parseArray(datasource.getDsSchema(), LensDsSchema.class));
        datasourceOutVO.setDsSql(JSON.parseObject(datasource.getDsSql(), LensDsSql.class));
        datasourceOutVO.setMetric(JSON.parseObject(datasource.getMetric(), HashMap.class));
        datasourceOutVO.setTags(JSON.parseObject(datasource.getTags(), HashMap.class));
        datasourceOutVO.setCreatedTime(datasource.getCreatedTime().getTime());
        datasourceOutVO.setModifiedTime(datasource.getModifiedTime().getTime());
        return datasourceOutVO;
    }

    private void objectToString(LensDatasource datasource,LensDatasourceInVO datasourceInVO){
        datasource.setSource(JSON.toJSONString(datasourceInVO.getSource()));
        datasource.setDsSchema(JSONArray.toJSONString(datasourceInVO.getDsSchema()));
        datasource.setDsSql(JSON.toJSONString(datasourceInVO.getDsSql()));
        datasource.setMetric(JSON.toJSONString(datasourceInVO.getMetric()));
        datasource.setTags(JSON.toJSONString(datasourceInVO.getTags()));
    }


}
